using System;

using System.IO;

namespace PTP.Core
{
  public static class DataUtil
  {
    public static uint ReadUINT16(Stream bytes)
    {
      return (uint)bytes.ReadByte() | ((uint)bytes.ReadByte() << 8);
    }

    public static uint ReadUINT32(Stream bytes)
    {
      return (uint)bytes.ReadByte() | ((uint)bytes.ReadByte() << 8) | ((uint)bytes.ReadByte() << 16) | ((uint)bytes.ReadByte() << 24);
    }

    internal static uint ReadUINT64(Stream bytes)
    {
      return (uint)bytes.ReadByte() | ((uint)bytes.ReadByte() << 8) | ((uint)bytes.ReadByte() << 16) | ((uint)bytes.ReadByte() << 24) | ((uint)bytes.ReadByte() << 32) | ((uint)bytes.ReadByte() << 40) | ((uint)bytes.ReadByte() << 48) | ((uint)bytes.ReadByte() << 56);
    }

    public delegate void ArrayReader(uint arraySize, uint value);

    public static void ReadUINT16Array(Stream bytes, ArrayReader reader)
    {
      uint length = ReadUINT32(bytes);

      for (int i = 0; i < length; i++)
      {
        uint result = ReadUINT16(bytes);
        if (reader != null)
          reader(length, result);
      }
    }

    public static uint[] ReadUINT16ArrayToMemory(Stream bytes)
    {
      int tempListIndex = 0;
      uint[] tempList = null;
      ArrayReader reader = new ArrayReader(delegate(uint arraySize, uint value)
      {
        if (tempList == null)
        {
          tempList = new uint[arraySize];
        }
        tempList[tempListIndex++] = value;
      });
      ReadUINT16Array(bytes, reader);
      return tempList;
    }

    public static void ReadUINT32Array(Stream bytes, ArrayReader reader)
    {
      uint length = ReadUINT32(bytes);

      for (int i = 0; i < length; i++)
      {
        uint result = ReadUINT32(bytes);
        if (reader != null)
          reader(length, result);
      }
    }

    public static uint[] ReadUINT32ArrayToMemory(Stream bytes)
    {
      int tempListIndex = 0;
      uint[] tempList = null;
      ArrayReader reader = new ArrayReader(delegate(uint arraySize, uint value)
      {
        if (tempList == null)
        {
          tempList = new uint[arraySize];
        }
        tempList[tempListIndex++] = value;
      });
      ReadUINT32Array(bytes, reader);
      return tempList;
    }

    public static string ReadString(Stream bytes)
    {
      string result = null;
      int length = bytes.ReadByte();
      if ((length == 0) || (length == 1))
        return String.Empty;
      //TODO: fix this quick & dirty UTF-8 conversion
      byte[] buffer = new byte[length-1]; //the last char is terminating null
      for (int i = 0; i < buffer.Length; i++)
      {
        buffer[i] = (byte)bytes.ReadByte();
        bytes.ReadByte(); //discard second byte
      }
      bytes.ReadByte(); bytes.ReadByte(); //skip terminating null

      result = new string(System.Text.Encoding.UTF8.GetChars(buffer));
      return result;
    }

  }
}
